/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.huawei.healthecology.subscriber;

import com.huawei.healthecology.data.ble.callback.AdapterStateChangeCallback;
import com.huawei.healthecology.data.ble.data.BluetoothAdapterState;
import com.huawei.healthecology.data.ble.data.BluetoothEventAction;
import com.huawei.healthecology.data.utils.OptionalX;
import com.huawei.healthecology.log.LogUtil;

import lombok.NonNull;
import ohos.aafwk.content.Intent;
import ohos.bluetooth.BluetoothHost;
import ohos.event.commonevent.CommonEventData;
import ohos.event.commonevent.CommonEventSubscribeInfo;
import ohos.event.commonevent.CommonEventSubscriber;

import java.util.Locale;
import java.util.Optional;

/**
 * Subscriber BluetoothAdapter State
 */
public class BluetoothAdapterStateSubscriber extends CommonEventSubscriber {
    private static final String TAG = "BluetoothAdapterStateSubscriber";

    private static final int INVALID_STATE = -1;

    private static final int STATE_OFF = 10;

    private static final int STATE_TURNING_ON = 11;

    private static final int STATE_ON = 12;

    private static final int STATE_TURNING_OFF = 13;

    private final AdapterStateChangeCallback stateChangeCallback;

    /**
     * Instantiates  new Bluetooth adapter state subscriber
     *
     * @param subscribeInfo The subscribe info
     * @param stateChangeCallback The state change callback
     */
    public BluetoothAdapterStateSubscriber(CommonEventSubscribeInfo subscribeInfo,
        @NonNull AdapterStateChangeCallback stateChangeCallback) {
        super(subscribeInfo);
        this.stateChangeCallback = stateChangeCallback;
    }

    @Override
    public void onReceiveEvent(CommonEventData commonEventData) {
        Optional.ofNullable(commonEventData)
            .map(CommonEventData::getIntent)
            .ifPresent(this::dealWithActions);
    }

    private void dealWithActions(Intent info) {
        int currentState = Optional.ofNullable(info)
            .map(Intent::getParams)
            .filter(params -> !params.isEmpty())
            .map(intentParams -> intentParams.getParam(BluetoothHost.HOST_PARAM_CUR_STATE))
            .map(state -> getBluetoothState((int) state))
            .orElse(INVALID_STATE);
        String action = Optional.ofNullable(info)
            .map(Intent::getAction)
            .orElse("");
        if (currentState != INVALID_STATE
            && currentState != BluetoothHost.STATE_TURNING_ON
            && currentState != BluetoothHost.STATE_TURNING_OFF) {
            LogUtil.debug(TAG, String.format(Locale.ROOT, "Bluetooth receive action %1$s and state %2$d",
                action, currentState));
            BluetoothEventAction event = BluetoothEventAction.parseFrom(action);
            OptionalX.ofNullable(stateChangeCallback)
                .ifPresent(callback -> callback.onStateChange(BluetoothAdapterState.of(event, currentState)))
                .ifNotPresent(() -> LogUtil.info(TAG, "Bluetooth adapter subscriber call back not set"));
        } else {
            LogUtil.debug(TAG, "Current bluetooth adapter state is neither ON or OFF");
        }
    }

    private int getBluetoothState(int state) {
        switch (state) {
            case STATE_OFF:
                return BluetoothHost.STATE_OFF;
            case STATE_TURNING_ON:
                return BluetoothHost.STATE_TURNING_ON;
            case STATE_ON:
                return BluetoothHost.STATE_ON;
            case STATE_TURNING_OFF:
                return BluetoothHost.STATE_TURNING_OFF;
            default:
                return state;
        }
    }
}
